#!/usr/bin/env python
# -*- coding:utf-8 -*-

__author__ = 'cjay'

import random

class Deck(object):
    def __init__(self):
        self.cards = []

    def reset(self):
        self.cards = []
        for i in range(2,15):
            for j in ["c",'h','s','d']:
                self.cards.append("%s%d"%(j,i))
        random.shuffle(self.cards)

    @property
    def count(self):
        return len(self.cards)


    def getCard(self):
        card = self.cards[random.randint(0,self.count-1)]
        self.cards.remove(card)
        return card

    def print_cards(self):
        for i in self.cards:
            print i


def translateCards(p_cards):
    '''
    translate cards from format 'c2','h3' to (2,2),(3,1)

    @type p_cards: list
    @param p_cards: incomming list

    '''
    out = []
    for i in p_cards:
        t,v = i[0],int(i[1:])
        if t=='h': t=1
        elif  t=='c': t=2
        elif t=='d': t=3
        elif t=='s': t=4
        out.append((v,t))
    return out

def translateCombinationCode(p_in):
    '''
    return the string name of the combination from it`s code

    @type p_in: list
    @param p_in: incomming list

    '''
    if p_in==1: return "Royal Strait Flash"
    if p_in==2: return "Royal Strait"
    if p_in==3: return "Care"
    if p_in==4: return "Full House"
    if p_in==5: return "Flash"
    if p_in==6: return "Strait"
    if p_in==7: return "Set"
    if p_in==8: return "Two Pair"
    if p_in==9: return "Pair"
    if p_in==10: return "Kiker"




def parseCardState(p_cards):
    '''
    input: sequence of tuples where first element is card range and second - card type
    ** (14,1) - Ace of hearts
    ** (3,1) - 3 of hearts
    ** (9,2) - 9 of clumbs
    ** (*,3) - diamonds
    ** (*, 4) - spice

    return the value of sequence.
    1 - royal strait flash
    2 -  strait flash
    3 - care
    4 - full house
    5 - flash
    6 - Strait
    7 - Set  (tripple)
    8 - Two pair
    9 - pair
    10 - kiker

    output is a tuple with code of sequence, sequence, higher card and a lear

    @type p_cards: list
    @param p_cards: incomming list



    '''
    #    chaeck if it is Royal Flash
    is_royal_flash = True
    is_strait_ace = set()
    not_sequence = 0
    cards_sorted = p_cards[::]

    cards_sorted.sort(lambda x,y: (x[1]-y[1])*100+(x[0]-y[0]))
    same = {}
    flash = {}
    flash[cards_sorted[-1][1]]=1
    same[cards_sorted[-1][0]]=1
    for i, val in enumerate(cards_sorted[:-1]):
        if not flash.has_key(val[1]):
            flash[cards_sorted[i][1]] = 1
        else: flash[cards_sorted[i][1]] += 1

        is_strait_ace.add(cards_sorted[i+1][1])
        if not same.has_key(val[0]):
            same[val[0]]=1
        else:
            same[val[0]]=same[val[0]]+1

        if cards_sorted[i][0]!=(cards_sorted[i+1][0]-1):
            not_sequence+=1

    if not_sequence == 0:
        if len(is_strait_ace)==1:
            if cards_sorted[-1][0]==14:         # royal strait flash
                return (1,cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
            else:                              #  strait flash
                return (2,cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
        else:                                                # flash
            return (5, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])

    pairs = 0
    tripple = 0
    care = 0
    pairs_value = []        # list of pairs
    tripple_value = []        # list of tripple
    care_value = None        # list of tripple
    for i in same.iterkeys():
        if same[i]==2:
            pairs_value.append(i)
            pairs+=1

        if same[i]==3:
            tripple +=1
            tripple_value.append(i)
        if same[i]==4:
            care +=1
            care_value = i
    if care==1:
        return (3, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
    if tripple==1 and pairs==1:
        return (4, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
    for key,value  in flash.iteritems():
        if value==5:
            return (5, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])


    cards_sorted.sort(lambda x,y: (x[0]-y[0]))
    not_sequence = 0
    for i, val in enumerate(cards_sorted[:-1]):
        if cards_sorted[i][0]!=(cards_sorted[i+1][0]-1):
            not_sequence+=1

    if not_sequence==0:
        return (6, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])

    strait = set(cards_sorted)
    if strait == set([2,3,4,5,14]):
        return (6, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
    lst_strait = list(strait)
    is_strait = True
    for i,val in enumerate(lst_strait[:-1]):
        if val!=lst_strait[i+1]:
            is_strait = False
            break
    if is_strait:
        return (6, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])

    if tripple>0:
        return (7, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
    if pairs>1:
        return (8, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])
    if pairs==1:
        return (9, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])

    return (10, cards_sorted,cards_sorted[-1][0],cards_sorted[-1][1])

def get_pairs(p_lst):
    '''
    returns a list of pairs

    @type p_lst: list
    @param p_lst: incomming list

    '''
    same = sort_by_same(p_lst)
    out = []
    for i in same.keys():
        if len(same[i])==2:
            out.append(same[i])
    return out

def sort_by_lear(p_cards):
    '''
    разбивает карты по мастям на 4 списка

    @type p_cards: list
    @param p_cards: incomming list

    '''
    lears = [[],[],[],[]]
    for i in p_cards:
        lears[i[1]].append(i)
    return lears

def sort_by_same(p_lst):
    '''

    @type p_lst: list
    @param p_lst: incomming list

    '''
    same = {}
    for i in p_lst:
        if same.has_key(i[0]):
            same[i[0]].append(i)
        else:
            same[i[0]]=[i]
    return same


def sort_by_value_lear(p_cards):
    '''
    сортирует последовательность по масти и  возрастанию

    @type p_cards: list
    @param p_cards: incomming list

    '''
    cards_sorted = p_cards[::]
    cards_sorted.sort(lambda x,y: (x[1]-y[1])*100+(x[0]-y[0]))
    return cards_sorted


def can_be_royal_flush(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию ройал флеш в оставшейся колоде
    карты игрока пока не учитываются

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination

    >>> p_cards = [(10,0),(11,0),(12,0),(13,0),(9,1)]
    >>> p_player_cards = [(12,0),(4,4)]
    >>> p_pack = [(14,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    [(14, 0)]

    Pack has not combination

    >>> p_cards = [(10,0),(11,0),(12,0),(13,0),(9,1)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    None


    the same combination
    >>> p_cards = [(10,0),(11,0),(12,0),(13,0),(9,1)]
    >>> p_player_cards = [(14,0),(4,4)]
    >>> p_pack = [(14,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    [(14, 0)]

    '''
    lears = sort_by_lear(p_cards)
    step_one = False
    lear = -1
    for i in range(4):
        if len(lears[i])>2:
            step_one = True
            lear = i
    if not step_one: return None

    seq = [(10,lear),(11,lear),(12,lear),(13,lear),(14,lear)]
    for i in p_cards:
        if i[1]==lear:
            if i[0]>=10: seq.remove(i)
    for i in seq:
        if i not in p_pack:
            return None
    return seq


def can_be_straight_flash(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию стрейт флеш в оставшейся колоде
    карты игрока пока не учитываются

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination
        right addition
    >>> p_cards = [(5,0),(6,0),(7,0),(8,0),(9,1)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(9,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    [(9, 0)]

        lefrt addition
    >>> p_cards = [(5,0),(6,0),(7,0),(8,0),(9,1)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(4,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    [(4, 0)]

        center addition and left addition
    >>> p_cards = [(5,0),(6,0),(8,0),(9,1),(2,2)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(4,0),(5,2),(6,1),(2,4),(7,0),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    [(4, 0), (7, 0)]

        center addition and left addition is missing
    >>> p_cards = [(5,0),(6,0),(8,0),(9,1),(2,2)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(4,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    None

        Ace addition and right addition
    >>> p_cards = [(2,0),(3,0),(4,0),(9,1),(2,2)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(5,0),(14,0),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    [(14, 0), (5, 0)]

        Ace addition and left addition
    >>> p_cards = [(5,0),(3,0),(4,0),(9,1),(2,2)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(2,0),(14,0),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    [(2, 0), (14, 0)]

    Pack has not combination
    >>> p_cards = [(4,0),(5,0),(6,0),(7,0),(9,1)]
    >>> p_player_cards = [(14,1),(4,4)]
    >>> p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher
######################
    >>> p_cards = [(4,1),(5,0),(6,0),(7,0),(9,1)]
    >>> p_player_cards = [(8,0),(9,0)]
    >>> p_pack = [(4,0),(3,0),(6,1),(2,4),(10,1),(7,3),(2,0)]
    >>> print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    None


    the same combination
    > p_cards = [(4,0),(5,0),(6,0),(7,0),(9,1)]
    > p_player_cards = [(8,0),(4,4)]
    > p_pack = [(8,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_straight_flash(p_cards, p_player_cards, p_pack)
    None

    '''
    pl_cards = p_cards[::]
    pl_cards.extend(p_player_cards)
    pl_cards = sort_by_value_lear(pl_cards)
    same = {}
    for i in pl_cards:
        if not same.has_key(i[1]): same[i[1]]=[i]
        else:
            same[i[1]].append(i)
    print "same", same
    for i in same.keys():
        if len(same[i])>4:
            pl_cards = same[i]

    print "player_cards:", pl_cards

    sorted = sort_by_value_lear(p_cards)
    lears = sort_by_lear(sorted)
    next_step = False
    lear = -1
    for i in range(4):
        if len(lears[i])>2:
            lear = i
            next_step = True
    if not next_step: return None

    subseq = [lears[lear][0][0]]
    for i in lears[lear][1:]:
        if (i[0]-subseq[-1])<3:
            subseq.append(i[0])
    need = []
    min = subseq[0]
    max = subseq[-1]
    if max-min>=3:
        for i in range(min,max):
            if i not in subseq:
                need.append((i,lear))
    for i in need:
        if i not in p_pack: return None
    t_need = []
    diff = (len(subseq)+len(need))
    if diff==3:
        t_need.append([(min-1,lear),(max+1,lear)])
        t_need.append([(min-1,lear),(min-2,lear)])
        t_need.append([(max+1,lear),(max+2,lear)])
    if diff==4:
        t_need.append([(min-1,lear)])
        t_need.append([(max+1,lear)])
    out = []
    for i in t_need:
        if (0,lear) in i: continue
        if (14,lear) in i: continue
        if (15,lear) in i: continue
        if (16,lear) in i: continue
        addition = []
        for j in i:
            if j[0]==1:
                addition.append((14,lear))
            else:
                addition.append(j)
        out.append(addition)
    res = []
    for i in out:
        has = True
        for j in i:
            if j not in p_pack: has = False
        if has:
            res = i
            break
    res.extend(need)
    if len(res): return res
    return None

def can_be_kare(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию каре в оставшейся колоде
    карты игрока пока не учитываются

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack


    Player has not combination
    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(14,3),(5,2)]
    > p_pack = [(4,3),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_kare(p_cards, p_player_cards, p_pack)
    [(4, 0), (4, 1), (4, 2), (4, 3)]

    Pack has not combination
    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_kare(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher

    > p_cards = [(4,0),(4,1),(3,0),(3,1),(9,1)]
    > p_player_cards = [(4,2),(4,3)]
    > p_pack = [(3,2),(3,3),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_kare(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower
    > p_cards = [(4,0),(4,1),(7,0),(7,1),(9,1)]
    > p_player_cards = [(4,2),(4,3)]
    > p_pack = [(7,2),(7,3),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_kare(p_cards, p_player_cards, p_pack)
    [(7, 2), (7, 3)]

    '''
    same = sort_by_same(p_cards)
    card = None
    for i in same.keys():
        if len(same[i])>1:
            card = same[i]
    card_val = card[0][0]
    need = [(card_val,i) for i in range(4)]
    for i in card:
        if i in need: need.remove(i)
    has = True
    for i in need:
        if i not in p_cards: has = False
    if not has: return (False)
    return (True, need)


def can_be_full_house(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию фулл хаус в оставшейся колоде
    карты игрока пока не учитываются


    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination

    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(5,4)]
    > p_pack = [(9,0),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_full_house(p_cards, p_player_cards, p_pack)
    [(9, 0)]

    Pack has not combination
    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_full_house(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher
    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(9,2),(4,4)]
    > p_pack = [(8,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_full_house(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower
    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(3,1),(3,4)]
    > p_pack = [(8,1),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_full_house(p_cards, p_player_cards, p_pack)
    [(8, 1)]

    two pairs from pack
    > p_cards = [(4,0),(4,1),(4,2),(8,2),(9,1)]
    > p_player_cards = [(3,1),(3,4)]
    > p_pack = [(5,1),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_full_house(p_cards, p_player_cards, p_pack)
    [(5, 1), (5, 2)]

    '''
    pairs = {}
    for i in p_cards:
        if not pairs.has_key(i[0]): pairs[i[0]]=[i]
        else: pairs[i[0]].append(i)
    pair = []
    for i in pairs.keys():
        if len(pairs[i])>1:
            pair.append(pairs[i])
    cards = p_cards[::]
    for i in pair:
        for j in i:
            cards.remove(j)
    need = []
    if len(pair)>0:
        need = [(pair[0][0][0],i) for i in range(4) if (pair[0][0][0],i) not in pair[0]]
    if len(pair)==2:
        need.extend([(pair[1][0][0],i) for i in range(4) if (pair[1][0][0],i) not in pair[1]])
    has_tripple = False
    for i in pair:
        if len(i)>2: has_tripple = True
    if not has_tripple: need = [need]
    else: need = []
    if len(pair)==1:
        addition = []
        for i in cards:
            addition.extend([(i[0],j) for j in range(4) if j!=i[1]])
        need.append(addition)

    has = True
    out = []
    for i in need:
        for j in i:
            if j in p_pack:
                out.append(j)
                break

    return out

def can_be_flush(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию флеш в оставшейся колоде
    карты игрока пока не учитываются

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_flush(p_cards, p_player_cards, p_pack)
    None

    Pack has not combination
    > p_cards = [(4,0),(6,0),(7,0),(8,2),(9,1)]
    > p_player_cards = [(14,0),(5,0)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3)]
    > print can_be_flush(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher
    > p_cards = [(4,0),(6,0),(7,0),(8,2),(9,1)]
    > p_player_cards = [(14,0),(5,0)]
    > p_pack = [(3,0),(10,0),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_flush(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower
    > p_cards = [(4,0),(6,0),(7,0),(8,2),(9,1)]
    > p_player_cards = [(11,0),(5,0)]
    > p_pack = [(14,0),(13,0),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_flush(p_cards, p_player_cards, p_pack)
    [(13, 0), (14, 0)]

    '''
    lears = sort_by_lear(p_cards)
    seq = None
    for i in lears:
        if len(i)>2:
            seq = i
    if not seq: return False
    lear = seq[0][1]
    for i in p_pack:
        if i[1]==lear:
            seq.append(i)
            if len(seq)==5: break
    return seq

def can_be_strait(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию стрэйт в оставшейся колоде
    карты игрока пока не учитываются


    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination
###
    > p_cards = [(4,0),(5,1),(6,2),(7,2),(9,1)]
    > p_player_cards = [(14,1),(2,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_strait(p_cards, p_player_cards, p_pack)
    None

    Pack has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_strait(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_strait(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_strait(p_cards, p_player_cards, p_pack)
    None

    the same combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_strait(p_cards, p_player_cards, p_pack)
    None
    '''
    cards_sorted = p_cards[::]
    cards_sorted.sort(lambda x,y: x[0]-y[0])
    cards = []
    last = cards_sorted[0][0]-1
    for i in cards_sorted:
        if i[0]>last:
            cards.append(i)
            last = i[0]
    old = cards[0]
    middle_out = [[cards[0]]]
    for i in cards[1:]:
        if (i[0]-old[0])<=3:
            middle_out[-1].append(i)
            old = i
        else:
            middle_out.append([i])
            old = i
    res = None
    for i in middle_out:
        if len(i)>2:
            res = i
            break
    need = []
    old = res[0][0]-1
    for i in range(res[0][0], res[-1][0]):
        if old+1!=i:
            need.append(i)
        old = i
    count = len(res)+len(need)
    probably = []
    if count == 4:
        probably.append([res[0][0]-1,res[-1][0]+1])
    if count == 3:
        probably.append([res[0][0]-1,res[-1][0]+1])
        probably.append([res[0][0]-1,res[0][0]-2])
        probably.append([res[-1][0]+1,res[-1][0]+2])
    prob = []
    for i in probably:
        if 0 in i:continue
        if 15 in i: continue
        append = []
        for j in i:
            append.append(j if j!=1 else 14)
        prob.append(append)
    for i in need:
        prob.append([i])

    out = []
    for i in prob:
        ls = []
        for j in i:
            for k in p_pack:
                if k[0]==j:
                    ls.append(k)
                    break

        if len(ls)==len(i):
            out = ls
            break
    ls = []
    for i in need:
        has = False
        for j in p_pack:
            if j[0]==i:
                ls.append(j)
                has = True
                break
        if not has: return False
    out.extend(ls)
    return out if out else False

def can_be_three(p_cards,p_player_cards,p_pack):
    '''
    ищет  в оставшейся колоде комбинацию тройка старше чем у игрока

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_three(p_cards, p_player_cards, p_pack)
    None

    Pack has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_three(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_three(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_three(p_cards, p_player_cards, p_pack)
    None

    the same combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_three(p_cards, p_player_cards, p_pack)
    None

    '''
    same = sort_by_same(p_cards)
    has = False
    for i in same.keys():
        res = []
        for j in p_pack:
            if j[0]==i:
                same[i].append(j)
                res.append(j)
                if len(same[i])>2:
                    out = res
                    has = True

    if not has: return False
    return out

def can_be_two_pair(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию две пары в оставшейся колоде
    карты игрока пока не учитываются

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_two_pair(p_cards, p_player_cards, p_pack)
    None

    Pack has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_two_pair(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_two_pair(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_two_pair(p_cards, p_player_cards, p_pack)
    None

    the same combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_two_pair(p_cards, p_player_cards, p_pack)
    None

    '''
#    находим минимум доя нашего выйгрыша
    player_min = None
    if len(p_player_cards)==2:
        if p_player_cards[0][0]==p_player_cards[1][0]:       # если у игрока пара на руках
            player_min = p_player_cards[0][0]
    if not player_min:
        for i in p_player_cards:
            for j in p_cards:
                if i[0]==j[0] and i[0]>player_min:
                    player_min = i[0]
                    break
    print 'player_min',player_min
#    находим пары на столе
    pairs = get_pairs(p_cards)
#    находим непары на столе
    cards = p_cards[::]
    for i in pairs:
        print i
        for j in i:
            if j in cards: cards.remove(j)
    out = []
    print "cards", cards
    for i in cards:
        for j in p_pack:
            if j[0]==i[0]:
                if len(out)==0:
                    if j[0]<=player_min: continue
                out.append(i)

    print "out", out
    ss = {}
    if not out:
        same = sort_by_same(p_pack)
        ss = same
        for i in same.keys():
            if len(same[i])>1:
                out.extend(same[i][:2])
    print "ss_", ss
    if not out: return None
    print "len", len(pairs)
    print "oout", out
    if  (len(out)==1 and len(pairs)==0):
        print "need addition"
        for i in p_cards:
            for j in p_pack:
                if (j[0]==i[0]) and (j not in out):
                    out.append(j)
                    break
            if len(out)>1: break
    return out

def can_be_pair(p_cards,p_player_cards,p_pack):
    '''
    ищет комбинацию пары в оставшейся колоде, большую, чем у игрока


    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack


    Player has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_pair(p_cards, p_player_cards, p_pack)
    None

    Pack has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_pair(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_pair(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_pair(p_cards, p_player_cards, p_pack)
    None

    the same combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_pair(p_cards, p_player_cards, p_pack)
    None
    '''
    player_min = -1
    player = [f[0] for f in p_player_cards[::]]
    for i in p_cards:
        if i[0] in player and i[0]>player_min: player_min = i[0]
    same = sort_by_same(p_cards)
    out = []
    for i in p_pack:
        if i[0]<=player_min: continue
        if same.has_key(i[0]):
            out = [i]
            break
    if out: return out
    same = {}
    for i in p_pack:
        if i[0]<=player_min: continue
        if not same.has_key(i[0]): same[i[0]]=[i]
        else:
            same[i[0]].append(i)
            if len(same[i[0]])>1:
                out = same[i[0]][:2]
    return out

def can_be_kiker(p_cards,p_player_cards,p_pack):
    '''
    Возвращает старшую карту.
    Выше или равную карте игрока, если это возможно

    @type p_cards: list
    @param p_cards: cards on the table

    @type p_player_cards: list
    @param p_player_cards: player`s cards

    @type p_pack: list
    @param p_pack: cards from pack

    Player has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    None

    Pack has not combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    None

    player`s combination higher

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    None

    Player`s combination lower

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    None

    the same combination

    > p_cards = [(4,0),(6,1),(7,2),(8,2),(9,1)]
    > p_player_cards = [(14,1),(4,4)]
    > p_pack = [(6,2),(5,2),(6,1),(2,4),(10,1),(7,3),(2,0)]
    > print can_be_royal_flush(p_cards, p_player_cards, p_pack)
    None
    '''
    p_kicker = None
    min = -1
    for i in p_player_cards:
        if i[0]>min:
            min = i[0]
            p_kicker = min
    out = None
    for i in p_pack:
        if i[0]>p_kicker:
            out = i
            break
    if out: return [out]
    for i in p_pack:
        if i[0]>=p_kicker:
            out = i
            break
    if out: return [out]
    return None

if __name__=="__main__":
    p_cards = [(4,1),(5,0),(6,0),(7,0),(9,1)]
    p_player_cards = [(8,0),(9,0)]
    p_pack = [(4,0),(3,0),(6,1),(2,4),(10,1),(7,3),(2,0)]
    res =  can_be_straight_flash(p_cards, p_player_cards, p_pack)
    print res, ",",res == None




#    print can_be_kiker(p_cards,p_player_cards,p_pack)
#    print can_be_pair(p_cards,p_player_cards,p_pack)
    #print can_be_two_pair(p_cards,p_player_cards,p_pack)   #
#    print can_be_three(p_cards,p_player_cards,p_pack)
#    print can_be_strait(p_cards,p_player_cards,p_pack)
#    print can_be_flush(p_cards,p_player_cards,p_pack)
#    print can_be_full_house(p_cards,p_player_cards,p_pack)
#    print can_be_kare(p_cards,p_player_cards,p_pack)
#    print can_be_straight_flash(p_cards,p_player_cards,p_pack)
#    print find_need_combination(cards,2,[(3,3),(5,1),(4,2)])
#    print parseCardState([(2,1),(3,1),(5,1),(6,1),(7,1),(8,1),(4,1)])